package com.yanyu.space.common.log.support;

import com.yanyu.space.common.log.handler.LogFactory;
import com.yanyu.space.common.log.handler.LogWorkerContext;
import com.yanyu.space.common.sleuth.util.TracerWebUtil;
import lombok.AllArgsConstructor;
import org.apache.catalina.connector.RequestFacade;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.util.AntPathMatcher;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author yanyu
 */
@AllArgsConstructor
public class LogWebFilter implements Filter {
    private List<String> excludePatterns;
    private List<String> includePatterns;
    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    private List<String> defaultExcludePatterns = Arrays.asList("/**/*.js", "/**/*.png", "/**/*.css", "/**/*.html", "/favicon.ico",
            "/swagger/**", "/api-docs/**", "/actuator/**", "/webjars/**");

    public LogWebFilter(List<String> excludePatterns, List<String> includePatterns) {
        if (CollectionUtils.isNotEmpty(excludePatterns)) {
            this.excludePatterns = excludePatterns;
        } else {
            this.excludePatterns = new ArrayList<>();
        }
        this.excludePatterns.addAll(defaultExcludePatterns);
        this.includePatterns = includePatterns;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 获取url
        String url = "";
        if (request instanceof RequestFacade) {
            url = ((RequestFacade) request).getRequestURI();
        } else if (request instanceof HttpServletRequest) {
            url = ((HttpServletRequest) request).getRequestURI();
        }

        // 匹配
        boolean traceFlag = false;
        if (CollectionUtils.isEmpty(includePatterns)) {
            traceFlag = true;
            for (String excludePattern : excludePatterns) {
                if (antPathMatcher.match(excludePattern, url)) {
                    traceFlag = false;
                }
            }

        } else {
            for (String excludePattern : includePatterns) {
                if (antPathMatcher.match(excludePattern, url)) {
                    traceFlag = true;
                    break;
                }
            }
        }

        // 断言
        if (traceFlag) {
            try (LogWorkerContext logWorkerContext = LogFactory.getInstance().start(TracerWebUtil.getTraceContextInRequest(request))) {
                try {
                    chain.doFilter(request, response);
                } finally {
                }
            }
        } else {
            chain.doFilter(request, response);
        }
    }
}
